package com.service.impl;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dto.DataDictionaryDTO;
import com.entity.DataDictionary;
import com.mapper.DataDictionaryMapper;
import com.service.DataDictionaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.List;

import static com.constant.RedisConstant.*;

/**
 * <p>
 * 数据字典表 服务实现类
 * </p>
 *
 * @author 马磊
 * @since 2023-02-16
 */
@Service
public class DataDictionaryServiceImpl extends ServiceImpl<DataDictionaryMapper, DataDictionary> implements DataDictionaryService {

    @Resource
    private DataDictionaryMapper dataDictionaryMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 初始化数据
     * @return
     */
    @Override
    public List<DataDictionaryDTO> getInitData(Integer type) {
        if (type==null){
            return null;
        }
        String json = redisTemplate.opsForValue().get(DATA_DICTIONARY + type);
        if (StrUtil.isNotBlank(json)){
            List<DataDictionaryDTO> list = JSONUtil.toList(json, DataDictionaryDTO.class);
            return list;
        }
        if (json!=null){
            return null;
        }
        List<DataDictionaryDTO> list;
        try {
            boolean b = tryLock(MUTEX + type);
            if (!b){ //重试
                getInitData(type);
            }
            list = dataDictionaryMapper.selectByType(type);
            if (list==null){
                redisTemplate.opsForValue().set(DATA_DICTIONARY + type,"",Duration.ofMinutes(NULL_TIME));
                return null;
            }
            redisTemplate.opsForValue().set(DATA_DICTIONARY + type,JSONUtil.toJsonStr(list), Duration.ofMinutes(DATA_DICTIONARY_TIME));
        } catch (Exception e){
            throw new RuntimeException(e);
        } finally {
            unlock(MUTEX + type);
        }
        return list;
    }

    /**
     * 获得锁
     * @param key
     * @return
     */
    private boolean tryLock(String key) {
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "1", Duration.ofSeconds(MUTEX_TIME));
        return BooleanUtil.isTrue(flag);
    }

    /**
     * 释放锁
     * @param key
     */
    private void unlock(String key) {
        redisTemplate.delete(key);
    }

}
